import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt

class ClusterUtils(object):
    def __init__(self):
        """初始化并加载景区数据"""
        self.df = pd.read_csv('./scenic_data.csv')  # 假设数据文件名为scenic_data.csv
    
    def get_k(self):
        """
        使用轮廓系数确定最佳聚类数量
        返回:
            optimal_k (int): 最佳聚类数
        """
        # 1. 特征选取和标准化
        features = self.df[['non_weekend_ratio', 'out_province_ratio', 'elderly_ratio']]
        scaler = StandardScaler()
        scaler_features = scaler.fit_transform(features)
        
        # 2. 计算不同k值的轮廓系数
        scores = []
        for k in range(2, 6):  # 测试k=2到5
            kmeans = KMeans(n_clusters=k, random_state=42)
            labels = kmeans.fit_predict(scaler_features)
            scores.append(silhouette_score(scaler_features, labels))
        
        # 3. 可视化结果
        plt.figure(figsize=(8, 5))
        plt.plot(range(2, 6), scores, marker='o', color='b')
        plt.xlabel('聚类数量(k)')
        plt.ylabel('轮廓系数')
        plt.title('不同聚类数量下的轮廓系数')
        plt.grid(True)
        plt.show()
        
        # 4. 返回最佳k值（轮廓系数最大时）
        optimal_k = range(2, 6)[scores.index(max(scores))]
        print(f"最佳聚类数量: {optimal_k}")
        return optimal_k

    def perform_clustering(self, k=None):
        """
        执行聚类分析
        参数:
            k (int): 指定聚类数，若为None则自动计算最佳k
        返回:
            DataFrame: 包含聚类结果的数据
        """
        # 1. 自动确定k值（如果未指定）
        if k is None:
            k = self.get_k()
        
        # 2. 准备特征数据
        features = self.df[['non_weekend_ratio', 'out_province_ratio', 'elderly_ratio']]
        scaler = StandardScaler()
        scaler_features = scaler.fit_transform(features)
        
        # 3. 执行K-means聚类
        kmeans = KMeans(n_clusters=k, random_state=42)
        self.df['cluster'] = kmeans.fit_predict(scaler_features)
        
        # 4. 分析聚类特征
        print("\n各聚类特征均值:")
        print(self.df.groupby('cluster').mean())
        
        # 5. 可视化聚类结果（示例展示前两个特征）
        plt.figure(figsize=(10, 6))
        for i in range(k):
            cluster_data = self.df[self.df['cluster'] == i]
            plt.scatter(
                cluster_data['out_province_ratio'], 
                cluster_data['non_weekend_ratio'],
                label=f'Cluster {i}'
            )
        plt.xlabel('外省游客比例')
        plt.ylabel('非周末游玩比例')
        plt.title('景区游客特征聚类结果')
        plt.legend()
        plt.grid(True)
        plt.show()
        
        return self.df

if __name__ == '__main__':
    # 使用示例
    analyzer = ClusterUtils()
    
    # 方法1：仅确定最佳k值
    best_k = analyzer.get_k()
    
    # 方法2：完整聚类分析（自动确定k）
    result_df = analyzer.perform_clustering()
    
    # 方法3：指定k值进行分析
    # result_df = analyzer.perform_clustering(k=3)